using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.IO;
using System.Linq;
using Unity.Mathematics;
using Unity.VisualScripting;
using UnityEngine.Networking;
using UnityEngine.Serialization;


public class PlayMusic : MonoBehaviour
{
    private float beat_timer = 0f;
    private float last_print_timer = 0f;
    private float next_time = -1f;
    
    private int beat_index = 0;
    private int beat_length = 0;

    [Header("暂停标识")] public bool flag_stop = false;
    [Header("开始立刻播放音乐")]  public bool play_on_start = false;
    // [Header("是否开始")] public bool is_play = true;
    
    public bool is_playing => AudioVolumeManager.instance.bgm_audio_source_comp.isPlaying;
    
    [Header("节拍延迟")]
    public float beat_delay = 0.5f;
    [Header("最小间隔")]
    public float beat_min_interval = 0.5f;
    [Header("最小振幅")]
    public float min_y_value = 0.05f;

    private List<float> rhythm_ls;
    private List<float> y_peaks;

    [Header("节拍按钮的父级")]
    public Transform beats_parent_trans;

    private float init_bgm_volume;

    [Header("音效播放组件")]
    public AudioSource base_audio_source_comp;

    [Header("音效测试文件")]
    public string clip_name = "haha.mp3";

    [Header("BGM节奏文件")]
    public string rhythm_file_name = "calling_4.json";
    
    [Header("BGM音乐文件")]
    public string bgm_file_name = "calling.mp3";
    
    public void btn_play_clip()
    {
        // bgm_audio_source_comp.volume = BdTools.Values.base_volume;
        //
        // var clip = base_audio_clip_dc[clip_name];
        // base_audio_source_comp.clip = clip;
        // base_audio_source_comp.Play();
        
        AudioVolumeManager.instance.play_audio(clip_name);
        
        // if (!base_audio_source_comp.isPlaying)
        // {
        //     base_audio_source_comp.Play();
        // }
        // else
        // {
        //     base_audio_source_comp.Stop();
        //     // base_audio_source_comp.Pause();
        //     // base_audio_source_comp.UnPause();
        // }
    }
    
    /// <summary>
    /// 携程加载音频
    /// </summary>
    /// <param name="audio_source">音频组件</param>
    /// <param name="music_path">暂时仅支持[`mp3`, `wav`]格式</param>
    /// <param name="auto_play">自动播放</param>
    /// <param name="volume">音量设置</param>
    /// <returns></returns>
    private IEnumerator IELoadExternalAudioWebRequest(AudioSource audio_source, string music_path, bool auto_play=true, float volume = -1f)
    {
        AudioType _audioType;
        
        BdUtils.check_file_extension(music_path, new List<string>(){"mp3", "wav"});
        if (BdUtils.check_file_extension(music_path, "mp3", raise_error: false))
        {
            _audioType = AudioType.MPEG;
        }
        else
        {
            _audioType = AudioType.WAV;
        }


        if (music_path.StartsWith(Application.persistentDataPath))
        {
            music_path = "file://" + music_path;
            BdPackage.BdUtils.log("--- StartsWith persistentDataPath --- new music_path:", music_path);
        }
        UnityWebRequest _unityWebRequest = UnityWebRequestMultimedia.GetAudioClip(music_path, _audioType);
        yield return _unityWebRequest.SendWebRequest();

        if(_unityWebRequest.result == UnityWebRequest.Result.ProtocolError || _unityWebRequest.result == UnityWebRequest.Result.ConnectionError)
        {
            Debug.Log("*** GetAudioClip Error:" + _unityWebRequest.error.ToString());
        }
        else
        {
            AudioClip _audioClip = DownloadHandlerAudioClip.GetContent(_unityWebRequest);
            audio_source.clip = _audioClip;
            if (volume >= 0)
            {
                BdPackage.BdUtils.log($"audio_source --- volume: {volume}, music_path: {music_path}");
                audio_source.volume = volume;
            }
            if (auto_play)
            {
                if (_audioType == AudioType.MPEG)
                {
                    _audioClip.LoadAudioData();
                    float clipLength = _audioClip.length;
                    Debug.Log("playing ~~~ 音频剪辑长度`clipLength`为: " + clipLength + " 秒");
                }
                audio_source.Play();
            }
        }
    }

    // private float original_animator_speed__idle;
    // private float original_animator_speed__shift;
    public Dictionary<string, float> original_animator_speed_dc = new Dictionary<string, float>()
    {
        {"idle", 1f},
        {"shift", 1f}
    };
    
    void Start()
    {
        // original_animator_speed__shift = lihua_animator.speed;
        // original_animator_speed__idle = lihua_animator.speed;
        // original_animator_speed_dc = new Dictionary<string, float>()
        // {
        //     {"idle", 1f},
        //     {"shift", 1f}
        // };

        AudioVolumeManager.instance.init_volume();
        BdUtils.assert(bgm_audio_source_comp, "`audio_source_comp`不能为空!");

        string music_file_name = $"music/{bgm_file_name}";
        string music_file_path = BdTools.get_static_abs_file_path_on_all_platform(music_file_name);
        BdUtils.assert(File.Exists(music_file_path), $"`music_file_path`[{music_file_path}]不存在?");
        StartCoroutine(IELoadExternalAudioWebRequest(bgm_audio_source_comp, music_file_path, volume: BdTools.Values.bgm_volume, auto_play: play_on_start));

        var audio_name_ls = new List<string>()
        {
            // "wave_lash_1.mp3",
            // "wave_lash_2.mp3",
            "hit_by_lash.mp3",
            "haha.mp3",
            "haha.wav",
        };
        foreach (var audio_name_i in audio_name_ls)
        {
            string _audio_path_i =  $"audio/{audio_name_i}";
            string audio_path_i = BdTools.get_static_abs_file_path_on_all_platform(_audio_path_i);
            StartCoroutine(AudioVolumeManager.instance.load_audio_clip_to_dc(AudioVolumeManager.instance.audio_clip_dc, audio_path_i, audio_name_i));
        }
        
        // string rhythm_file_path
        string _rhythm_file_path = BdUtils.join("rhythm", rhythm_file_name);
        string rhythm_file_path = BdTools.get_static_abs_file_path_on_all_platform(_rhythm_file_path);
        // string rhythm_file_path = BdUtils.join(BdUtils.data_table_dir_path, "rhythm", "calling_1.json");
        
        BdUtils.assert(File.Exists(rhythm_file_path), $"rhythm_file_path[{rhythm_file_path}]不存在?");

        string json = File.ReadAllText(rhythm_file_path);
        var beats_dc = BdUtils.conv_json_to_dict(json);
        
        var music_timer = BdUtils.conv_to_float(beats_dc["timer"]);
        var speed = BdUtils.conv_to_float(beats_dc["speed"]);
        // var frame_interval = BdUtils.conv_to_float(beats_dc["frame_interval"]);

        rhythm_ls = BdUtils.conv_obj_to_list<float>(beats_dc["rhythm"]);
        y_peaks = BdUtils.conv_obj_to_list<float>(beats_dc["y_peaks"]);

        beat_length = rhythm_ls.Count;
        
        BdPackage.BdUtils.log( $"beat_length: {beat_length}, rhythm_ls:", BdUtils.conv_obj_to_list(rhythm_ls.Take(5)));

        // BdUtils.log($"music_timer: {music_timer.ToString("F2")}, speed: {speed}, frame_interval: {frame_interval.ToString("F2")}");
        BdPackage.BdUtils.log($"music_timer: {music_timer.ToString("F2")}, speed: {speed}");

        var new_obj = BdTools.get_game_object_by_path("/Beats/center");
        
        string _img_path = BdUtils.join( "images", "lihua_images", "g_front_alert.png");
        string img_path = BdTools.get_static_abs_file_path_on_all_platform(_img_path);

        Vector2 img_size = new Vector2(200, 300);
        BdTools.load_img_to_obj_sprite_renderer(new_obj, img_path, img_size: img_size);
        
        audio_parent_trans = BdTools.get_game_object_by_path("/ObjectPoolParent/AudioParent").transform;

        animation_dc = new Dictionary<AnimationType, string>();
        
        animation_dc.Add(AnimationType.pause, "pause");
        animation_dc.Add(AnimationType.idle, "idle");
        animation_dc.Add(AnimationType.attack_left, "attack_left");
        animation_dc.Add(AnimationType.attack_right, "attack_right");
    }
    
    public Animator lihua_animator;

    public Quaternion RotateTransformByDirection(Transform trans, bool is_right_direction = true)
    {
        int rotate_y = is_right_direction ? 180 : 0;
        var old_rotation = trans.rotation;
        var new_rotation = new Quaternion(old_rotation.x, rotate_y, old_rotation.z, old_rotation.w);
        trans.rotation = new_rotation;
        return new_rotation;
    }
    
    void create_beat_obj(float y_value, float score, float delta_time = 0)
    {
        bool y_positive = y_value > 0 ? true : false;
        float y_p = y_value > 0 ? 1 : -1;
        
        // BdUtils.log($"------ next_time: {next_time} --- y_positive: {y_positive} --- y_value: {y_value.ToString("F2")}");

        string beat_obj_name = y_positive ? "positive_beat" : "negative_beat";
        var new_obj = ObjectPool.instance.GetObj(beat_obj_name, prefab_path: "Prefabs/beats");

        string state_name = y_value > 0? "shift": "idle";
        
        if (delta_time > 0)
        {
            float speed = lihua_animator.speed;
            // AnimatorStateInfo stateInfo = lihua_animator.GetCurrentAnimatorStateInfo(0);
            // 获取当前动画播放的时间 (normalizedTime)
            // float normalizedTime = stateInfo.normalizedTime;
            // Debug.Log("Normalized Time: " + normalizedTime);

            // 计算实际播放时间
            // float actualTime = normalizedTime / speed;
            // Debug.Log("Actual Play Time: " + actualTime);
            // lihua_animator.frame
            
            // 获取当前动画的总长度时间
            AnimatorClipInfo[] clipInfo = lihua_animator.GetCurrentAnimatorClipInfo(0); // 这里的0表示基础层
            AnimationClip clip = clipInfo[0].clip;
            float old_animation_len = clip.length;

            float new_animation_len = delta_time;
            BdPackage.BdUtils.log("old_animation_len: " + old_animation_len, "--- new_animation_len:", new_animation_len);

            float newSpeed = old_animation_len / new_animation_len;
            lihua_animator.speed = newSpeed;
        }
        else
        {
            lihua_animator.speed = original_animator_speed_dc[state_name];
        }

        lihua_animator.Play(state_name);
        
        // if (y_value > 0)
        // {
        //     // var new_rotation = RotateTransformByDirection(lihua_animator.transform, is_right_direction: true);
        //     // BdPackage.BdUtils.log("--- 1 new_rotation:", new_rotation);
        //     state_name = "shift";
        //
        //     lihua_animator.Play(state_name);
        // }
        // else
        // {
        //     // var new_rotation = RotateTransformByDirection(lihua_animator.transform, is_right_direction: false);
        //     // BdPackage.BdUtils.log("--- 2 new_rotation:", new_rotation);
        //
        //     // state_name = "BeHit";
        //     state_name = "idle";
        //     
        //     lihua_animator.Play(state_name);
        // }

        if (score > 0)
        {
            StartCoroutine(_show_imgs__sidestep(new_obj, y_value));
        }
        else
        {
            StartCoroutine(_show_imgs__be_hit(new_obj, y_value, score));
        }
        
        ObjectPoolManager.instance.recycle_obj(new_obj, 1f);
    }

    // Update is called once per frame
    private float last_update_time = -1.0f;

    public Transform audio_parent_trans;

    private AudioSource bgm_audio_source_comp => AudioVolumeManager.instance.bgm_audio_source_comp;
    
    public Animator attacker_animator;

    private BdTools.TimeIntervalUtil animation_timer = new BdTools.TimeIntervalUtil(interval: 0.1f);

    public void btn_replay()
    {
        next_time = -1f;
        last_update_time = -1.0f;

        beat_index = 0;
        
        beat_timer = 0f;
        last_print_timer = 0f;
    
        AudioVolumeManager.instance.btn_replay_bgm();
    }

    private string last_press_key = "";
    private float last_press_time = -1f;
    private float score_interval = 0.5f;
    
    void Update()
    {
        if (flag_stop)
            return;
        
        if (animation_timer.is_time_to_run())
        {
            if (Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.Keypad1))
            {
                last_press_key = "left";
                last_press_time = beat_timer;
                
                BdUtils.log("~~~ animation_dc: attack_left");
                attacker_animator.Play(animation_dc[AnimationType.attack_left]);
            }
            else if (Input.GetKey(KeyCode.D) || Input.GetKey(KeyCode.Keypad3))
            {
                last_press_key = "right";
                last_press_time = beat_timer;

                BdUtils.log("~~~ animation_dc: attack_right");
                attacker_animator.Play(animation_dc[AnimationType.attack_right]);
            }
            else
            {
                // BdUtils.log("~~~ animation_dc: idle");
                attacker_animator.Play(animation_dc[AnimationType.idle]);
            }
        }
        
        if (!is_playing)
        {
            // BdUtils.log("~~~ animation_dc: pause");
            attacker_animator.Play(animation_dc[AnimationType.pause]);
            return;
        }
        
        beat_timer += Time.deltaTime;

        if (next_time == -1f)  // 初始
            next_time = rhythm_ls[beat_index];
        
        if (next_time == -2f)  // 结束
            return;
        
        if (beat_timer < next_time + beat_delay || beat_timer < last_update_time + beat_min_interval)
        {
            return;
        }
    
        last_update_time = beat_timer;

        float y_value = y_peaks[beat_index];

        if (Mathf.Abs(y_value) < min_y_value)
            return;

        bool y_positive = y_value > 0 ? true : false;

        float score = 0;
        if (beat_timer - last_press_time < score_interval)
        {
            if ((last_press_key == "right" && y_positive == true) || (last_press_key == "left" && y_positive == false))
            {
                score = 1;
                BdUtils.log("=== 得1分!");
            }
        }
        
        last_print_timer = beat_timer;
        
        beat_index += 1;
        if (beat_index >= beat_length)
            next_time = -2f;  // 结束
        else
            next_time = rhythm_ls[beat_index];

        float delta_time = next_time == -2f ? 0 : next_time - beat_timer; 
        create_beat_obj(y_value, score, delta_time);
    }

    [Header("图片大小")]
    public Vector2 img_size = new Vector2(300, 200);

    IEnumerator _show_imgs__be_hit(GameObject new_obj, float y_value, float score)
    {
        yield return null;
    }
    
    IEnumerator _show_imgs__sidestep(GameObject new_obj, float y_value)
    {
        int total_frames = 2;
        float interval = beat_min_interval / total_frames;  // 释放间隔
        
        bool y_positive = y_value > 0 ? true : false;
        float y_p = y_value > 0 ? 1 : -1;

        new_obj.transform.SetParent(beats_parent_trans);

        for (var i = 0; i < total_frames; i++)
        {
            string img_path;
            if (i % 2 == 0)
            {
                img_path = BdTools.get_static_abs_file_path_on_all_platform(BdUtils.join( "images", "lihua_images", "g_left_1.png"));
            }
            else
            {
                img_path = BdTools.get_static_abs_file_path_on_all_platform(BdUtils.join( "images", "lihua_images", "g_left_2.png"));
                // img_path = BdUtils.join(BdUtils.streamingAssetsPath, "images", "lihua_images", "g_left_2.png");
            }

            // Vector2 img_size = new Vector2(300, 200);
            BdTools.load_img_to_obj_sprite_renderer(new_obj, img_path, img_size: img_size);
            // BdTools.load_img_to_obj_sprite_renderer(new_obj, img_path);
            
            // float offset_x = BdUtils.get_random_float(-5, 5);
            // float position_x = Mathf.Clamp(y_value * 10, -5, 5);
            float position_x = y_p * (3 + 1.0f * i); 
        
            new_obj.transform.position = new Vector3(position_x, 0, 0);
        
            new_obj.SetActive(true);

            yield return new WaitForSeconds(interval);
        }
    }
    
    public enum AnimationType
    {
        pause, idle, attack_left, attack_right
    }
    
    Dictionary<AnimationType, string> animation_dc;
    
}